package HW.hw4;

/**************************************************************
* Class CapitalGain
* @author Jeff Thomas - Thomas007
* @vesion 1.0.0
* Date: 03.17.2008
* Copyright 2008, Jeff Thomas
***************************************************************/
import java.io.*;
import java.util.*;

public class CapitalGain
{
private static Queue<Share> shareQueue = new LinkedList<Share>();
	public static void main(String[] args)
	{
		output(readData());
	}
/**************************************************************
* Read Data
* @return - int value of the total capital gain 
* Task:	1. Read lines from in.dat or in2.dat file
*			2. Tokenize each string to determine buy/sell, number
*				of shares, and cost of shares
*			3. When we buy shares, create a Share object and call
*				buyShare()
*			4. Call sellShare() when we sell shares
* Side Effects: Has try/catch blocks for both IOException and
*					FileNotFoundException
***************************************************************/	
	public static int readData()
	{
		int grandGain = 0;
		try 
		{
			BufferedReader br = new BufferedReader(new FileReader("in.dat"));
			String line; //String that holds each line from our file
			int numShares = 0;
			int costShares = 0;
			boolean buyOrSell = false; //true = buy, false = sell
			try
			{
				while ((line = br.readLine()) != null)
				{
					StringTokenizer st = new StringTokenizer(line);
					while (st.hasMoreTokens())
					{
						String token = st.nextToken();
						if (token.equals("buy"))
							buyOrSell = true;
						else if (token.equals("sell"))
							buyOrSell = false;
						else if (isNumeric(token))
							numShares = Integer.parseInt(token);
						else if (token.substring(0,1).equals("$"))
							costShares = Integer.parseInt(token.substring(1));
					}
					if (buyOrSell == true)
					{
						Share newShare = new Share(numShares, costShares);
						buyShare(newShare);
					}
					else
					{
						grandGain = grandGain + sellShare(numShares, costShares);
					}
				}
			}
			catch (IOException e)
			{
				System.err.println("IOException: " + e.getMessage());
			}
		}
		catch (FileNotFoundException e)
		{
			System.err.println("FileNotFoundException: " + e.getMessage());
		}
		return grandGain;
	}
/**************************************************************
* Ouput
* @param totalGain - integer value of total gain/loss or +/-
* Task:	1. Determine whether the gain is positive or negative
*			2. Print out gain or loss, taking the absolute value
*				for loss.
* Side Effects: None
***************************************************************/		
	public static void output(int totalGain)
	{
		if (totalGain >= 0)
			System.out.println("Total capital gain is $" + 
																	totalGain);
		else
			System.out.println("Total capital loss is $" + 
														Math.abs(totalGain));
	}
/**************************************************************
* Buy Share
* @param newShare - Share object of bought stock
* Task:	1. Offer Share object to the Queue
* Side Effects: None
***************************************************************/		
	public static void buyShare(Share newShare)
	{
		shareQueue.offer(newShare);
	}
/**************************************************************
* Sell Share
* @return - integer for that days gain/loss
* @param numShares - 
* @param costShares -  
* Task:	1. Loop while we still have shares to sell and the 
*				Queue is not empty
*			2. if we sold all the shares from one day, remove that
*				share from the Queue and calculate the gain
*			3. Else we want to modify the remaining shares for that
*				day and calculate the gain
* Side Effects: None
***************************************************************/	
	public static int sellShare(int numShares, int costShares)
	{
		int totalGain = 0;
		while (numShares > 0 && shareQueue.peek() != null)
		{
			Share nextShare = shareQueue.peek();
			if (nextShare.getNum() <= numShares)
			{
				shareQueue.poll();
				totalGain = totalGain + (nextShare.getNum() * 
										(costShares - nextShare.getCost()));
				numShares = numShares - nextShare.getNum();
			}
			else
			{
				totalGain = totalGain + (numShares * 
										(costShares - nextShare.getCost()));
				nextShare.setNum(nextShare.getNum() - numShares);
				numShares = 0;
			}
		}
		return totalGain;
	}
/**************************************************************
* Is Numeric
* @return - boolean value if the string is an Integer
* @param str - String to be tested if it's a integer
* Task:	1. Use a try/catch block to parse the string to a integer
* Side Effects: None
***************************************************************/		
	private static boolean isNumeric(String str)
	{
   	try {
   		Integer.parseInt(str);
   		return true;
   	} 
		catch (NumberFormatException e)
		{
   		return false;
   	}
	}
}
/**************************************************************
* Share Object
* Task:	1. A share object that contains number of shares and
*				cost of those shares
*			2. Methods are provided to get and set cost and number
* Side Effects: None
***************************************************************/	
class Share
{
	private int numShare;
	private int costShare;
	
	public Share(int num, int cost)
	{
		numShare = num;
		costShare = cost;
	}
	
	public int getCost()
	{
		return costShare;
	}
	public int getNum()
	{
		return numShare;
	}
	
	public void setNum(int number)
	{
		numShare = number;
	}
}
/**************************************************************
* I, Jeff Thomas, certify that each part of this program was
* written by me, except as noted within the code.
*
*						_________________________
***************************************************************/